#include <iostream>
#include <unistd.h>
#include <vector>
#include "Thread.hpp"
#include"LockGuard.hpp"
using namespace std;
using namespace ThreadModule;

int g_tickets = 10000;
const int num = 4;
class ThreadData
{
public:
    ThreadData(int &tickets, const std::string &name, pthread_mutex_t& mutex)
        : _tickets(tickets), _name(name), _total(0),_mutex(mutex)
    {
    }
    ~ThreadData()
    {
    }

public:
    int &_tickets; // 所有的线程，最后都会引用同一个全局的g_tickets
    std::string _name;
    int _total;
    pthread_mutex_t &_mutex;
};
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//申请一个全局锁
void route(ThreadData* td)
{
    while (true)
    {
        {
            //pthread_mutex_lock(&td->_mutex);
            LockGuard guard(&td->_mutex);
            if (td->_tickets > 0) // 1
            {
                usleep(1000);
                printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); // 2
                td->_tickets--;                                                           // 3
                td->_total++;
                //pthread_mutex_unlock(&td->_mutex);
            }
            else
            {
                //pthread_mutex_unlock(&td->_mutex);
                break;
            }
        }
    }
}
// void route(int &tickets)
// {
//     while (true)
//     {
//         if (tickets > 0)
//         {
//             usleep(1000);
//             printf("get tickets: %d\n", tickets);
//             tickets--;
//         }
//         else
//         {
//             break;
//         }
//     }
// }
int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex,nullptr);

    vector<Thread<ThreadData*>> threads;
    vector<ThreadData*> datas;
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        ThreadData *td = new ThreadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name);
        datas.emplace_back(td);
    }
    for (auto &thread : threads)
    {
        thread.Start();
    }

    // 3. 等待一批线程
    for (auto &thread : threads)
    {
        thread.Join();
        // std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
    }
    for (auto data : datas)
    {
        std::cout << data->_name << " : " << data->_total << std::endl;
        delete data;
    }
    pthread_mutex_destroy(&mutex);
    return 0;
}
